home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_064 / examples / display / myreadpict.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  364 lines

  1. /** myReadPict.c ************************************************************
  2.  *
  3.  * Read an ILBM raster image file.               23-Jan-86.
  4.  *
  5.  * Modified version of ReadPict.c 
  6.  *   by Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
  7.  *   This software is in the public domain.
  8.  *
  9.  * Modified by C. Scheppner  11/86
  10.  *   Handles CAMG chunks for HAM, etc.
  11.  *   Calls user defined routine getBitMap(ilbmFramePtr) when it
  12.  *      reaches the BODY.
  13.  *   getBitMap() can open a screen of the correct size using
  14.  *      information this rtn places in the ilbmFrame, and returns
  15.  *      a pointer to a BitMap structure.  The BitMap structure
  16.  *      tells myReadPicture where it should load the bit planes.
  17.  *
  18.  * Modified by C. Scheppner  12/86
  19.  *   Loads in CCRT or CRNG chunks (converts CCRT to CRNG)
  20.  *
  21.  ****************************************************************************/
  22.  
  23. #define LOCAL   static
  24.  
  25. #include "intuition/intuition.h"
  26. #include "libraries/dos.h"
  27. #include "libraries/dosextens.h"
  28. #include "iff/ilbm.h"
  29. #include "myreadpict.h"    /* cs */
  30.  
  31. /* Define size of a temporary buffer used in unscrambling the ILBM rows.*/
  32. #define bufSz 512
  33.  
  34. /*------------ ILBM reader -----------------------------------------------*/
  35. /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
  36.  * We allocate one of these on the stack for every LIST or FORM encountered
  37.  * in the file and use it to hold BMHD & CMAP properties. We also allocate
  38.  * an initial one for the whole file.
  39.  * We allocate a new GroupContext (and initialize it by OpenRIFF or
  40.  * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
  41.  * just a context for reading (nested) chunks.
  42.  *
  43.  * If we were to scan the entire example file outlined below:
  44.  *    reading          proc(s)                new               new
  45.  *
  46.  * --whole file--   myReadPicture+ReadIFF GroupContext        ILBMFrame
  47.  * CAT              ReadICat                GroupContext
  48.  *   LIST           GetLiILBM+ReadIList       GroupContext        ILBMFrame
  49.  *     PROP ILBM    GetPrILBM                   GroupContext
  50.  *       CMAP       GetCMAP
  51.  *       BMHD       GetBMHD
  52.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  53.  *       BODY       GetBODY
  54.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  55.  *       BODY       GetBODY
  56.  *   FORM ILBM      GetFoILBM                 GroupContext        ILBMFrame
  57.  */
  58.  
  59. /* NOTE: For a small version of this program, set Fancy to 0.
  60.  * That'll compile a program that reads a single FORM ILBM in a file, which
  61.  * is what DeluxePaint produces. It'll skip all LISTs and PROPs in the input
  62.  * file. It will, however, look inside a CAT for a FORM ILBM.
  63.  * That's suitable for 90% of the uses.
  64.  *
  65.  * For a fancier version that handles LISTs and PROPs, set Fancy to 1.
  66.  * That'll compile a program that dives into a LIST, if present, to read
  67.  * the first FORM ILBM. E.g. a DeluxePrint library of images is a LIST of
  68.  * FORMs ILBM.
  69.  *
  70.  * For an even fancier version, set Fancy to 2. That'll compile a program
  71.  * that dives into non-ILBM FORMs, if present, looking for a nested FORM ILBM.
  72.  * E.g. a DeluxeVideo C.S. animated object file is a FORM ANBM containing a
  73.  * FORM ILBM for each image frame. */
  74. #define Fancy  0
  75.  
  76. /* Global access to client-provided pointers.*/
  77. LOCAL ILBMFrame *giFrame = NULL;   /* "client frame".*/
  78.  
  79.  
  80.  
  81. IFFP handleCAMG(context,frame)
  82. GroupContext *context;
  83. ILBMFrame    *frame;
  84.    {
  85.    IFFP iffp = IFF_OKAY;
  86.  
  87.    frame->foundCAMG = TRUE;
  88.    iffp = GetCAMG(context, &frame->camgChunk);
  89.    return(iffp);
  90.    }
  91.  
  92. IFFP handleCRNG(context,frame)
  93. GroupContext *context;
  94. ILBMFrame    *frame;
  95.    {
  96.    IFFP iffp = IFF_OKAY;
  97.  
  98.    if(frame->cycleCnt < maxCycles)
  99.       {
  100.       iffp = GetCRNG(context,&(frame->crngChunks[frame->cycleCnt]));
  101.       frame->cycleCnt++;
  102.       }
  103.    return(iffp);
  104.    }
  105.  
  106.  
  107. IFFP handleCCRT(context,frame)
  108. GroupContext *context;
  109. ILBMFrame    *frame;
  110.    {
  111.    CcrtChunk  ccrtTmp;
  112.    CrngChunk  *ptCrng;
  113.    IFFP iffp = IFF_OKAY;
  114.  
  115.    if(frame->cycleCnt < maxCycles)
  116.       {
  117.       iffp = GetCCRT(context, &ccrtTmp);
  118.       ptCrng = &(frame->crngChunks[frame->cycleCnt]);
  119.       if(ccrtTmp.direction)  ccrtTmp.direction = -ccrtTmp.direction;
  120.       ptCrng->active = ccrtTmp.direction & 0x03;
  121.       ptCrng->low = ccrtTmp.start;
  122.       ptCrng->high = ccrtTmp.end;
  123.  
  124.       /* Convert  CCRT secs/msecs to CRNG timimg
  125.        * 0x4000 = max CRNG rate  (cycle every 1 60th sec)
  126.        * This must be divided by # 60th's between cycles
  127.        * seconds to 60th's is easy
  128.        * msecs to 60th's requires division by 16667
  129.        * this is int math so I add 8334 (half 16667) first for rounding
  130.        */
  131.       ptCrng->rate = 0x4000 /
  132.          ((ccrtTmp.seconds * 60)+((ccrtTmp.microseconds+8334)/16667));
  133.       frame->cycleCnt++;
  134.       }
  135.    return(iffp);
  136.    }
  137.  
  138.  
  139. /** GetFoILBM() *************************************************************
  140.  *
  141.  * Called via myReadPictureto handle every FORM encountered in an IFF file.
  142.  * Reads FORMs ILBM and skips all others.
  143.  * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
  144.  * finds no BODY or if it has no BMHD to decode the BODY.
  145.  *
  146.  * Once we find a BODY chunk, we'll call user rtn getBitMap() to
  147.  *    allocate the bitmap and planes (or screen) and then read
  148.  *    the BODY into the planes.
  149.  *
  150.  ****************************************************************************/
  151. LOCAL BYTE bodyBuffer[bufSz];
  152. IFFP GetFoILBM(parent)  GroupContext *parent;
  153.    {
  154.    /*compilerBug register*/ IFFP iffp;
  155.    GroupContext formContext;
  156.    ILBMFrame ilbmFrame;      /* only used for non-clientFrame fields.*/
  157.    struct BitMap *destBitMap;   /* cs */
  158.  
  159.    /* Handle a non-ILBM FORM. */
  160.    if (parent->subtype != ID_ILBM)
  161.       {
  162. #if Fancy >= 2
  163.       /* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
  164.       iffp = OpenRGroup(parent, &formContext);
  165.       CheckIFFP();
  166.       do {
  167.          iffp = GetF1ChunkHdr(&formContext);
  168.          } while (iffp >= IFF_OKAY);
  169.       if (iffp == END_MARK)
  170.          {
  171.          iffp = IFF_OKAY;   /* then continue scanning the file */
  172.          }
  173.       CloseRGroup(&formContext);
  174.       return(iffp);
  175. #else
  176.       return(IFF_OKAY); /* Just skip this FORM and keep scanning the file.*/
  177. #endif
  178.       }
  179.  
  180.    ilbmFrame = *(ILBMFrame *)parent->clientFrame;
  181.    iffp = OpenRGroup(parent, &formContext);
  182.    CheckIFFP();
  183.  
  184.    do switch (iffp = GetFChunkHdr(&formContext)) {
  185.       case ID_BMHD: {
  186.          ilbmFrame.foundBMHD = TRUE;
  187.          iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
  188.          break; }
  189.       case ID_CAMG: {       /* cs */
  190.          iffp = handleCAMG(&formContext, &ilbmFrame);
  191.          break; }
  192.       case ID_CRNG: {       /* cs */
  193.          iffp = handleCRNG(&formContext, &ilbmFrame);
  194.          break; }
  195.       case ID_CCRT: {       /* cs */
  196.          iffp = handleCCRT(&formContext, &ilbmFrame);
  197.          break; }
  198.       case ID_CMAP: {
  199.          ilbmFrame.nColorRegs = maxColorReg; /* room for this many */
  200.          iffp = GetCMAP(&formContext, (WORD *)ilbmFrame.colorMap,
  201.                            &ilbmFrame.nColorRegs);
  202.          break; }
  203.       case ID_BODY: {       /* cs */
  204.          if (!ilbmFrame.foundBMHD)
  205.             {
  206.             iffp = BAD_FORM;   /* No BMHD chunk! */
  207.             }
  208.          else
  209.             {
  210.             if(destBitMap=(struct BitMap *)getBitMap(&ilbmFrame))
  211.                {
  212.                iffp = GetBODY( &formContext,
  213.                                destBitMap,
  214.                                NULL,
  215.                                &ilbmFrame.bmHdr,
  216.                                bodyBuffer,
  217.                                bufSz);
  218.                if (iffp == IFF_OKAY) iffp = IFF_DONE;   /* Eureka */
  219.                *giFrame = ilbmFrame; /* copy fields to client frame */
  220.                }
  221.             else
  222.                {
  223.                iffp = CLIENT_ERROR;   /* not enough RAM for the bitmap */
  224.                }
  225.             }
  226.          break; }
  227.  
  228.       case END_MARK: {
  229.          iffp = BAD_FORM;
  230.          break; }
  231.  
  232.       } while (iffp >= IFF_OKAY);
  233.       /* loop if valid ID of ignored chunk or a
  234.        * subroutine returned IFF_OKAY (no errors).*/
  235.  
  236.    if (iffp != IFF_DONE)  return(iffp);
  237.  
  238.    CloseRGroup(&formContext);
  239.    return(iffp);
  240.    }
  241.  
  242. /** Notes on extending GetFoILBM ********************************************
  243.  *
  244.  * To read more kinds of chunks, just add clauses to the switch statement.
  245.  * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
  246.  * the switch statement in GetPrILBM, too.
  247.  *
  248.  * To read a FORM type that contains a variable number of data chunks--e.g.
  249.  * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
  250.  * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
  251.  * case do whatever cleanup you need.
  252.  *
  253.  ****************************************************************************/
  254.  
  255.  
  256. /** GetPrILBM() *************************************************************
  257.  *
  258.  * Called via myReadPicture to handle every PROP encountered in an IFF file.
  259.  * Reads PROPs ILBM and skips all others.
  260.  *
  261.  ****************************************************************************/
  262. #if Fancy
  263. IFFP GetPrILBM(parent)  GroupContext *parent;  {
  264.    /*compilerBug register*/ IFFP iffp;
  265.    GroupContext propContext;
  266.    ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
  267.  
  268.    if (parent->subtype != ID_ILBM)
  269.       return(IFF_OKAY);   /* just continue scaning the file */
  270.  
  271.    iffp = OpenRGroup(parent, &propContext);
  272.    CheckIFFP();
  273.  
  274.    do switch (iffp = GetPChunkHdr(&propContext)) {
  275.       case ID_BMHD: {
  276.          ilbmFrame->foundBMHD = TRUE;
  277.          iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
  278.          break; }
  279.       case ID_CAMG: {       /* cs */
  280.          iffp = handleCAMG(&propContext, ilbmFrame);
  281.          break; }
  282.       case ID_CRNG: {       /* cs */
  283.          iffp = handleCRNG(&propContext, ilbmFrame);
  284.          break; }
  285.       case ID_CCRT: {       /* cs */
  286.          iffp = handleCCRT(&propContext, ilbmFrame);
  287.          break; }
  288.       case ID_CMAP: {
  289.          ilbmFrame->nColorRegs = maxColorReg; /* room for this many */
  290.          iffp = GetCMAP(&propContext,
  291.                           (WORD *)&ilbmFrame->colorMap,
  292.                              &ilbmFrame->nColorRegs);
  293.          break; }
  294.       } while (iffp >= IFF_OKAY);
  295.         /* loop if valid ID of ignored chunk or a
  296.          * subroutine returned IFF_OKAY (no errors).*/
  297.  
  298.    CloseRGroup(&propContext);
  299.    return(iffp == END_MARK ? IFF_OKAY : iffp);
  300.    }
  301. #endif
  302.  
  303. /** GetLiILBM() *************************************************************
  304.  *
  305.  * Called via myReadPicture to handle every LIST encountered in an IFF file.
  306.  *
  307.  ****************************************************************************/
  308. #if Fancy
  309. IFFP GetLiILBM(parent)  GroupContext *parent;  {
  310.     ILBMFrame newFrame;   /* allocate a new Frame */
  311.  
  312.     newFrame = *(ILBMFrame *)parent->clientFrame;  /* copy parent frame */
  313.  
  314.     return( ReadIList(parent, (ClientFrame *)&newFrame) );
  315.     }
  316. #endif
  317.  
  318. /** myReadPicture() ********************************************************/
  319. IFFP myReadPicture(file,iFrame)
  320.    LONG file;
  321.    ILBMFrame *iFrame;   /* Top level "client frame".*/
  322.    {
  323.    IFFP iffp = IFF_OKAY;
  324.  
  325. #if Fancy
  326.    iFrame->clientFrame.getList = GetLiILBM;
  327.    iFrame->clientFrame.getProp = GetPrILBM;
  328. #else
  329.    iFrame->clientFrame.getList = SkipGroup;
  330.    iFrame->clientFrame.getProp = SkipGroup;
  331. #endif
  332.    iFrame->clientFrame.getForm = GetFoILBM;
  333.    iFrame->clientFrame.getCat  = ReadICat ;
  334.  
  335.    /* Initialize the top-level client frame's property settings to the
  336.     * program-wide defaults. This example just records that we haven't read
  337.     * any BMHD property or CMAP color registers yet. For the color map, that
  338.     * means the default is to leave the machine's color registers alone.
  339.     * If you want to read a property like GRAB, init it here to (0, 0). */
  340.  
  341.    iFrame->foundBMHD  = FALSE;
  342.    iFrame->nColorRegs = 0;
  343.    iFrame->foundCAMG  = FALSE;    /* cs */
  344.    iFrame->cycleCnt   = 0;        /* cs */
  345.    giFrame = iFrame;
  346.  
  347.   /* Store a pointer to the client's frame in a global variable so that
  348.    * GetFoILBM can update client's frame when done.  Why do we have so
  349.    * many frames & frame pointers floating around causing confusion?
  350.    * Because IFF supports PROPs which apply to all FORMs in a LIST,
  351.    * unless a given FORM overrides some property.  
  352.    * When you write code to read several FORMs,
  353.    * it is ssential to maintain a frame at each level of the syntax
  354.    * so that the properties for the LIST don't get overwritten by any
  355.    * properties specified by individual FORMs.
  356.    * We decided it was best to put that complexity into this one-FORM example,
  357.    * so that those who need it later will have a useful starting place.
  358.    */
  359.  
  360.    iffp = ReadIFF(file, (ClientFrame *)iFrame);
  361.    return(iffp);
  362.    }
  363.  
  364.